/*!
 *  \file       GaussianSignalGenerator.cpp
 *  \brief      Implementazione della classe \c GaussianSignalGenerator
 *  \author     Davide Scola <S2299453@studenti.unige.it>
 *  \author	Minetti Alberto <S3064777@studenti.unige.it>
 *  \version    1.0
 *
 */
#include <cmath>
#include "ISignalGenerator.hpp"
#include "GaussianSignalGenerator.hpp"

using namespace std;


/*!
 *  \brief	Costruttore della classe \c GaussianSignalGenerator
 *
 *  \see	GaussianSignalGenerator< tType >::GaussianSignalGenerator( GaussianSignalGenerator< tType > const& other )
 *  \see	GaussianSignalGenerator< tType >::GaussianSignalGenerator( const tType mean, const tType variance, const unsigned long int nItems )
 */
template< class tType >
GaussianSignalGenerator< tType >::GaussianSignalGenerator( const unsigned long int nItems )
    : mean_( tType( 0 ) ),
      variance_( tType( 1 ) ),
      currPoint_( tType( 0 ) )
{
  this->iStep_ = tType( 2 ) / tType( nItems );
}

/*!
 *  \brief	Costruttore della classe \c GaussianSignalGenerator
 *
 *  \see	GaussianSignalGenerator< tType >::GaussianSignalGenerator( const unsigned long int nItems )
 *  \see	GaussianSignalGenerator< tType >::GaussianSignalGenerator( GaussianSignalGenerator< tType > const& other )
 */
template< class tType >
GaussianSignalGenerator< tType >::GaussianSignalGenerator( const tType mean, const tType variance, const unsigned long int nItems )
    : mean_( mean ),
      variance_( variance ),
      currPoint_( tType( 0 ) )
{
  this->iStep_ = tType( 2 ) / tType( nItems );
}

/*!
 *  \brief      Costruttore di copia della classe \c GaussianSignalGenerator
 *  \param[in]	other	generatore da copiare
 *
 *  \see	GaussianSignalGenerator< tType >::GaussianSignalGenerator( const unsigned long int nItems )
 *  \see	GaussianSignalGenerator< tType >::GaussianSignalGenerator( const tType mean, const tType variance, const unsigned long int nItems )
 */
template< class tType >
GaussianSignalGenerator< tType >::GaussianSignalGenerator( GaussianSignalGenerator< tType > const& other )
    : mean_( (&other)->mean_ ),
      variance_( (&other)->variance_ ),
      currPoint_( (&other)->currPoint_ ),
      iStep_( (&other)->iStep_ )
{
}


/*!
 *  \brief      Operatore di assegnazione della classe \c GaussianSignalGenerator
 */
template < typename tType > GaussianSignalGenerator< tType >&
GaussianSignalGenerator< tType >::operator=( const GaussianSignalGenerator& other )
{
   if (this == &other) {
       return *this;
   }
   
   this->mean_ = (&other)->mean_;
   this->variance_ = (&other)->variance_;
   this->currPoint_ = (&other)->currPoint_;
   this->iStep_ = (&other)->iStep_;
   
   return *this;
}


/*!
 *  \brief      Generatore del segnale
 *  \return	ritorna un segnale di tipo Gaussiano nell'intervallo [-1, 1]
 */
template< class tType > tType
GaussianSignalGenerator< tType >::operator() ( void )
{
  tType swap = this->currPoint_;
  
  if( ( this->currPoint_ += this->iStep_ ) == tType( 1 ) )
    this->currPoint_ = tType( -1 );
  
  return ( 1 / ( this->variance_ * tType( sqrt( 2 * M_PI ) ) ) ) *
        exp( ( -pow( swap - this->mean_, 2 ) ) / ( 2 * pow( this->variance_, 2 ) ) );
}
